from tabnanny import verbose
from typing import Optional, Type, List
import requests
from datetime import datetime

from langchain_core.tools import BaseTool, ToolException
from pydantic import BaseModel, Field
from app.config.settings import settings

# 获取当前时间的辅助函数
def get_current_datetime() -> str:
    """获取当前完整时间信息"""
    now = datetime.now()
    weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    weekday = weekdays[now.weekday()]
    return f"{now.year}年{now.month}月{now.day}日{weekday} {now.hour:02d}:{now.minute:02d}"

def get_current_date() -> str:
    """获取当前日期，格式为中文描述"""
    today = datetime.now()
    return f"{today.year}年{today.month}月{today.day}日"

def get_today_description() -> str:
    """获取今天的描述"""
    today = datetime.now()
    weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    weekday = weekdays[today.weekday()]
    return f"今日({today.month}月{today.day}日{weekday})热点"

# 基础输入模型，包含时间信息
class BaseToolInput(BaseModel):
    """所有工具的基础输入模型"""
    current_time: str = Field(default_factory=get_current_datetime, description="当前时间信息，用于提供时间上下文")

# 基础搜索工具类
class BaseBaiduSearchTool(BaseTool):
    """基础百度搜索工具类，提供通用的搜索功能"""
    
    def _search_with_baidu(self, query: str, current_time: str = None, top_k: int = 5, recency_filter: str = "month") -> dict:
        """使用百度搜索API进行搜索
        
        Args:
            query: 搜索关键词
            current_time: 当前时间信息
            top_k: 返回结果数量
            recency_filter: 时间过滤器 (week, month, semiyear, year)
            
        Returns:
            搜索结果字典
        """
        try:
            # 如果没有提供时间信息，自动获取当前时间
            if current_time is None:
                current_time = get_current_datetime()
            
            # 在查询中添加时间上下文
            enhanced_query = f"当前时间：{current_time}。{query}"
            
            url = 'https://qianfan.baidubce.com/v2/ai_search/chat/completions'
            headers = {
                'X-Appbuilder-Authorization': f'Bearer {settings.BAIDU_SEARCH_API_KEY}',
                'Content-Type': 'application/json'
            }
            
            messages = [
                {
                    "content": enhanced_query,
                    "role": "user"
                }
            ]
            
            data = {
                "messages": messages,
                "search_source": "baidu_search_v2",
                "resource_type_filter": [{"type": "web", "top_k": top_k}],
                "search_recency_filter": recency_filter
            }
            
            response = requests.post(url, headers=headers, json=data, timeout=30)
            
            if response.status_code == 200:
                return response.json()
            else:
                raise ToolException(f"API请求失败，状态码: {response.status_code}, 错误信息: {response.text}")
                
        except requests.exceptions.Timeout:
            raise ToolException("搜索请求超时，请稍后重试")
        except requests.exceptions.RequestException as e:
            raise ToolException(f"网络请求失败: {str(e)}")
        except Exception as e:
            raise ToolException(f"搜索失败: {str(e)}")

# 百度搜索工具
class BaiduSearchInput(BaseToolInput):
    """百度搜索工具的输入"""
    query: str = Field(default="最新资讯", description="搜索关键词")

class BaiduSearchTool(BaseBaiduSearchTool):
    """百度搜索工具"""
    name: str = "baidu_search"
    description: str = "使用百度搜索引擎进行联网搜索，获取最新的网络信息。当用户询问实时信息、新闻、当前事件或需要最新数据时使用此工具。"
    args_schema: Type[BaseModel] = BaiduSearchInput
    
    def _run(self, query: str = "最新资讯", current_time: str = None) -> str:
        """运行百度搜索工具
        
        Args:
            query: 搜索关键词
            current_time: 当前时间信息
            
        Returns:
            搜索结果的字符串形式
        """
        result = self._search_with_baidu(query, current_time)
        
        # 提取搜索结果并格式化
        if 'references' in result:
            formatted_results = []
            for ref in result.get('references', [])[:5]:  # 限制返回前5个结果
                title = ref.get('title', '无标题')
                content = ref.get('content', '无内容')
                url = ref.get('url', '')
                formatted_results.append(f"\n标题: {title}\n内容: {content}\n链接: {url}\n")
            
            return "\n".join(formatted_results)
        else:
            # 如果没有references字段，返回原始响应
            return str(result)

# 天气查询工具
class WeatherQueryInput(BaseToolInput):
    """天气查询工具的输入"""
    location: str = Field(default="南京", description="查询天气的地点，如：北京、上海、广州等")
    date: str = Field(default_factory=get_current_date, description="查询日期，如：今天、明天、后天，或具体日期如2024-01-01")

class WeatherQueryTool(BaseBaiduSearchTool):
    """天气查询工具"""
    name: str = "weather_query"
    description: str = "查询指定地点的实时天气信息，包括温度、湿度、风力、天气状况等。支持查询今天、明天或指定日期的天气预报。如果用户没有指定地点，默认查询南京的天气。"
    args_schema: Type[BaseModel] = WeatherQueryInput
    
    def _run(self, location: str = "南京", date: str = None, current_time: str = None) -> str:
        """运行天气查询工具
        
        Args:
            location: 查询地点
            date: 查询日期
            current_time: 当前时间信息
            
        Returns:
            天气信息的字符串形式
        """
        # 如果没有提供日期，使用当前日期
        if date is None:
            date = get_current_date()
            
        # 构建天气查询语句
        query = f"{location}{date}天气预报"
        
        result = self._search_with_baidu(query, current_time, top_k=5, recency_filter="week")
        
        # 专门针对天气信息进行格式化
        if 'references' in result:
            weather_info = []
            weather_info.append(f"📍 {location} {date}天气信息：\n")
            
            for ref in result.get('references', [])[:3]:  # 天气信息只取前3个最相关的结果
                title = ref.get('title', '无标题')
                content = ref.get('content', '无内容')
                url = ref.get('url', '')
                
                # 过滤和格式化天气相关内容
                if any(keyword in title.lower() or keyword in content.lower() 
                       for keyword in ['天气', '温度', '气温', '降雨', '风力', '湿度', '预报']):
                    weather_info.append(f"🌤️ {title}")
                    weather_info.append(f"   {content}")
                    weather_info.append(f"   来源: {url}\n")
            
            if len(weather_info) > 1:  # 如果有天气相关信息
                return "\n".join(weather_info)
            else:
                return f"抱歉，未能获取到 {location} {date}的详细天气信息，请尝试更具体的地点名称。"
        else:
            # 如果没有references字段，返回原始响应
            return str(result)

# 实时新闻工具
class NewsQueryInput(BaseToolInput):
    """新闻查询工具的输入"""
    topic: str = Field(default_factory=get_today_description, description="新闻主题或关键词")
    category: str = Field(default="综合", description="新闻分类，如：科技、财经、体育、娱乐、综合等")

class NewsQueryTool(BaseBaiduSearchTool):
    """实时新闻查询工具"""
    name: str = "news_query"
    description: str = "查询最新的新闻资讯，支持按主题和分类筛选。获取实时新闻、热点事件、行业动态等信息。如果用户没有指定主题，默认查询今日热点新闻。"
    args_schema: Type[BaseModel] = NewsQueryInput
    
    def _run(self, topic: str = None, category: str = "综合", current_time: str = None) -> str:
        """运行新闻查询工具
        
        Args:
            topic: 新闻主题
            category: 新闻分类
            current_time: 当前时间信息
            
        Returns:
            新闻信息的字符串形式
        """
        # 如果没有提供主题，使用当前日期的热点
        if topic is None:
            topic = get_today_description()
            
        # 构建新闻查询语句
        if category != "综合":
            query = f"{category} {topic} 最新新闻"
        else:
            query = f"{topic} 最新新闻资讯"
        
        result = self._search_with_baidu(query, current_time, top_k=8, recency_filter="week")
        
        # 专门针对新闻信息进行格式化
        if 'references' in result:
            news_info = []
            news_info.append(f"📰 {topic} 相关新闻：\n")
            
            for i, ref in enumerate(result.get('references', [])[:5], 1):  # 取前5条新闻
                title = ref.get('title', '无标题')
                content = ref.get('content', '无内容')
                url = ref.get('url', '')
                
                news_info.append(f"{i}. 📄 {title}")
                news_info.append(f"   摘要: {content[:200]}{'...' if len(content) > 200 else ''}")
                news_info.append(f"   链接: {url}\n")
            
            return "\n".join(news_info)
        else:
            return str(result)

# 股票查询工具
class StockQueryInput(BaseToolInput):
    """股票查询工具的输入"""
    stock_code: str = Field(default="上证指数", description="股票代码或股票名称，如：000001、平安银行、茅台等")

class StockQueryTool(BaseBaiduSearchTool):
    """股票查询工具"""
    name: str = "stock_query"
    description: str = "查询股票的实时价格、涨跌幅、成交量等信息。支持A股、港股等股票查询。如果用户没有指定股票，默认查询上证指数。"
    args_schema: Type[BaseModel] = StockQueryInput
    
    def _run(self, stock_code: str = "上证指数", current_time: str = None) -> str:
        """运行股票查询工具
        
        Args:
            stock_code: 股票代码或名称
            current_time: 当前时间信息
            
        Returns:
            股票信息的字符串形式
        """
        query = f"{stock_code} 股票实时行情价格"
        
        result = self._search_with_baidu(query, current_time, top_k=5, recency_filter="week")
        
        # 专门针对股票信息进行格式化
        if 'references' in result:
            stock_info = []
            stock_info.append(f"📈 {stock_code} 股票信息：\n")
            
            for ref in result.get('references', [])[:3]:  # 取前3个最相关的结果
                title = ref.get('title', '无标题')
                content = ref.get('content', '无内容')
                url = ref.get('url', '')
                
                # 过滤股票相关内容
                if any(keyword in title.lower() or keyword in content.lower() 
                       for keyword in ['股票', '股价', '行情', '涨跌', '成交', '市值', '指数']):
                    stock_info.append(f"💰 {title}")
                    stock_info.append(f"   {content}")
                    stock_info.append(f"   来源: {url}\n")
            
            if len(stock_info) > 1:
                return "\n".join(stock_info)
            else:
                return f"抱歉，未能获取到 {stock_code} 的详细股票信息，请检查股票代码是否正确。"
        else:
            return str(result)

# 汇率查询工具
class ExchangeRateInput(BaseToolInput):
    """汇率查询工具的输入"""
    from_currency: str = Field(default="人民币", description="源货币，如：人民币、美元、欧元等")
    to_currency: str = Field(default="美元", description="目标货币，如：美元、欧元、日元等")

class ExchangeRateTool(BaseBaiduSearchTool):
    """汇率查询工具"""
    name: str = "exchange_rate"
    description: str = "查询实时汇率信息，支持各种货币之间的汇率转换。如果用户没有指定货币，默认查询人民币对美元的汇率。"
    args_schema: Type[BaseModel] = ExchangeRateInput
    
    def _run(self, from_currency: str = "人民币", to_currency: str = "美元", current_time: str = None) -> str:
        """运行汇率查询工具
        
        Args:
            from_currency: 源货币
            to_currency: 目标货币
            current_time: 当前时间信息
            
        Returns:
            汇率信息的字符串形式
        """
        query = f"{from_currency}对{to_currency}汇率 实时汇率"
        
        result = self._search_with_baidu(query, current_time, top_k=5, recency_filter="week")
        
        # 专门针对汇率信息进行格式化
        if 'references' in result:
            rate_info = []
            rate_info.append(f"💱 {from_currency} → {to_currency} 汇率信息：\n")
            
            for ref in result.get('references', [])[:3]:  # 取前3个最相关的结果
                title = ref.get('title', '无标题')
                content = ref.get('content', '无内容')
                url = ref.get('url', '')
                
                # 过滤汇率相关内容
                if any(keyword in title.lower() or keyword in content.lower() 
                       for keyword in ['汇率', '兑换', '外汇', '汇价', '货币']):
                    rate_info.append(f"💰 {title}")
                    rate_info.append(f"   {content}")
                    rate_info.append(f"   来源: {url}\n")
            
            if len(rate_info) > 1:
                return "\n".join(rate_info)
            else:
                return f"抱歉，未能获取到 {from_currency} 对 {to_currency} 的详细汇率信息。"
        else:
            return str(result)

# 修改get_available_tools函数
def get_available_tools() -> List[BaseTool]:
    """获取所有可用的工具
    
    Returns:
        工具列表
    """
    return [
        BaiduSearchTool(),
        WeatherQueryTool(),
        NewsQueryTool(),
        StockQueryTool(),
        ExchangeRateTool(),
    ]